from time import strftime, localtime, sleep
from selenium.webdriver import ActionChains
import pytest
from selenium.webdriver.support.select import Select
from typing_extensions import Literal
import allure
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from common.Loger_log import write_loging, error_loging, get_project_path
import os

class BasePage(object):
    def __init__(self , driver):
        self.driver = driver
    def get_element(self ,loc):
        '''获取元素方法，loc是一个元组，'''
        self.WebDriverWait_visiblity(loc)
        return self.driver.find_element(*loc)


    def input_element(self, loc,text,page_name='模块XX'):
        '''定位元素输入元素，loc是一个元组，page_name= 所操作动作记录'''
        try:
            self.WebDriverWait_visiblity(loc)
            self.get_element(loc).send_keys(text)
            write_loging(f"{page_name}，输入值:{text}")
        except Exception as error:
            error_loging(f"{page_name}输入失败,定位元素: {loc}\n【错误信息】: {error}")
            self.savee_screenshot(page_name)

    def click(self , loc,page_name='无标记模块信息'):
        '''定位元素点击，loc是一个元组，page_name= 所操作动作记录'''
        try:
            self.WebDriverWait_visiblity(loc)
            self.get_element(loc).click()
            write_loging(f"点击:{page_name}")
        except Exception as error:
            error_loging(f"点击失败: {page_name}，定位元素: {loc}\n【错误信息】:{error}")
            self.savee_screenshot(page_name)



    def WebDriverWait_visiblity(self, loc, timeout=5, poll=0.5):
        '''等待元素元素等待出现,loc是一个元素，timeout超时时间，poll是每0.5s之后重新查询元素，visibility_of=显示等待元素'''
        try:
            WebDriverWait(self.driver, timeout, poll).until(EC.visibility_of_element_located(loc))
        except:
            pass


    def clear(self, loc,page_name='无标记模块信息'):
        '''清空定位元素内容，page_name=所操作模块'''
        try:
            self.WebDriverWait_visiblity(loc)
            self.get_element(loc).clear()
            write_loging(f"清空:{page_name}")
        except Exception as error:
            error_loging(f"清空失败:{page_name}:元素:{loc}  \n【错误信息】:{error}")
            self.savee_screenshot(page_name)

    def savee_screenshot(self, page_name=None):
        try:
            '''保存失败截图 ,st获取时间戳，file_path拼接截图地址，截图，allure.attach.file加入到allure报告里面'''
            st = strftime('%Y-%m-%d-%H-%M-%S', localtime())  # 修改时间戳格式，避免使用冒号
            file_path = os.path.join(get_project_path(), 'screenshot', page_name+ st+'.png')  # 修改文件名连接方式，避免使用特殊字符
            self.driver.save_screenshot(file_path)
            allure.attach.file(file_path, page_name, attachment_type=allure.attachment_type.PNG)
            error_loging(f"失败截图，截取当前网页,保存到{file_path}")
        except Exception as error:
            error_loging(f'截图方法出错【错误信息】:{error}')


    def all_headers_windows(self):
        '''获取所有窗口句柄'''
        ele=self.driver.window_handles
        write_loging(f'当前浏览器窗口:{len(ele)}个')
        return ele

    def current_window_handle(self):  #获取当前窗口句柄
        '''获取当前窗口句柄'''
        sleep(2)
        current_window=self.driver.current_window_handle
        write_loging(f'获取当前窗口{current_window}')
        return current_window

    def get_text(self,loc,Tom: Literal['textContent', 'innerHTML', 'outerHTML'] = 'textContent',page_name=None):
        '''获取元素文本内容，loc是一个元组，page_name= 所操作动作记录,默认选择'textContent'
        get_attribute('textContent')会获取标签之间的文本内容
        get_attribute('innerHTML')会获取标签之间的完整 html
        get_attribute('outerHTML')获取当前标签的完整 html
        '''
        try:
            self.WebDriverWait_visiblity(loc)
            els=self.get_element(loc).get_attribute(Tom)
            write_loging(f'获取:{page_name}文本，文本值:{els.strip()}')
            return els
        except Exception as error:
            error_loging(f"获取{Tom}内容失败，定位元素:{loc}\n【错误信息】:{error}")
            self.savee_screenshot(page_name)
            


    def get_attribute(self,loc,value,page_name=None):
        '''获取元素属性值，loc是一个元组，value：例如class、ID....，page_name= 所操作动作记录'''
        try:
            self.WebDriverWait_visiblity(loc)
            ele=self.get_element(loc).get_attribute(value)
            write_loging(f'获取:{page_name}，属性值为：{value}')
            return  ele
        except Exception as error:
            error_loging(f"属性值获取失败定位元素:{loc}\n 【错误信息】:{error}")
            self.savee_screenshot(page_name)


    def scrollIntoView(self,loc,page_name='模块XX'):
        '''滑动到元素指定的位置执行 ,每1秒滑动一次，loc是一个元组，page_name= 所操作动作记录'''
        try:
            self.driver.execute_script("var q=document.documentElement.scrollTop=10000")
            ele=self.get_element(loc)
            self.driver.execute_script("arguments[0].scrollIntoView();", ele)
            write_loging(f'滑动到元素到：{page_name}')
        except Exception as error:
            error_loging(f"滑动到元素失败:{page_name}，定位元素:{loc}\n【错误信息】:{error}")
            self.savee_screenshot(page_name)



    def visibility_element(self,loc):
        '''判断元素是否存在不存在返回FALSE'''
        if self.driver.find_elements(*loc):
            self.WebDriverWait_visiblity(loc, timeout=4, poll=0.5)
            sumelenment=self.driver.find_elements(*loc)
            if len(sumelenment )<=0:
                return False
            else:
                return True
        else:
            return False

    def iframe_switch(self,loc,page_name=None):
        '''切换iframe--一个的情况，如果存在内嵌套多次调用就行'''
        try:
            self.WebDriverWait_visiblity(loc)
            self.driver.switch_to.frame(self.get_element(loc))
            write_loging(f'成功切换:iframe')
        except Exception as error:
            error_loging(f"切换iframe失败，定位元素:{loc}\n【错误信息】:{error}")
            self.savee_screenshot(page_name)

    def iframe_switche_exit(self,page_name='模块属'):
        '''退出iframe框架到最外层'''
        try:
            self.driver.switch_to.default_content()
            write_loging(f'退出iframe')
        except Exception as error:
            error_loging(f"退出iframe失败\n【错误信息】:{error}")
            self.savee_screenshot(page_name)

    def get_select(self,loc,select: Literal['index', 'value', 'text'],select_value):
        '''获取下拉框的值'''
        try:
            if select=='index':
                self.WebDriverWait_visiblity(loc)
                Select(self.get_element(loc)).select_by_index(select_value)
            elif select=='value':
                self.WebDriverWait_visiblity(loc)
                Select(self.get_element(loc)).select_by_value(select_value)
            elif select=='text':
                self.WebDriverWait_visiblity(loc)
                Select(self.get_element(loc)).select_by_visible_text(select_value)
            else:
                write_loging(f'下拉框选择方式错误')
            write_loging(f'获取下拉方式：{select}，获取属性值:{select_value}')
        except Exception as error:
            error_loging(f"获取下拉框值失败，定位元素:{loc}\n【错误信息】:{error}")
            self.savee_screenshot(page_name='下拉框选择错误')

    def get_alert(self,alret: Literal['accept', 'dismiss', 'text']='accept'):
        '''接受警告框,默认不传值使用accept'''
        try:
            if alret=='accept':
                self.driver.switch_to.alert.accept()
            elif alret=='dismiss':
                self.driver.switch_to.alert.dismiss()
            elif alret=='text':
                text=self.driver.switch_to.alert.text
                write_loging(f'警告框内容：{text}')
                return text
            else:
                write_loging(f'无allure方法')
        except Exception as error:
            error_loging(f"警告框接受失败\n【错误信息】:{error}")
            self.savee_screenshot(page_name='警告框接受错误')

    def get_ActionChain(self,loc,Action: Literal['move','click','double_click',]):
        '''获取动作链对象，loc是一个元组'''
        try:
            if Action=='move':
                self.WebDriverWait_visiblity(loc)
                ActionChains(self.driver).move_to_element(self.get_element(loc)).perform()
                write_loging(f'move移动到元素')
            elif Action=='click':
                self.WebDriverWait_visiblity(loc)
                ActionChains(self.driver).click(self.get_element(loc)).perform()
                write_loging(f'鼠标click点击元素')

            elif Action=='double_click':
                self.WebDriverWait_visiblity(loc)
                ActionChains(self.driver).double_click(self.get_element(loc)).perform()
                write_loging(f'鼠标double_click双击元素')
            else:
                write_loging(f'ActionChain方式错误，还没有封装可自行添加')
        except Exception as error:
            error_loging(f"获取动作链失败，定位元素:{loc}\n【错误信息】:{error}")



if __name__ == '__main__':
    pass
    # st = strftime('%Y-%m-%d-%H-%M-%S', localtime())  # 修改时间戳格式，避免使用冒号
    # file_path = os.path.join(get_project_path(), 'screenshot',  '断言失败'+ st +'.png')
    # print(file_path)



